package top.yongyan0624.controller;


import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import top.yongyan0624.common.lang.Result;
import top.yongyan0624.entity.SysUser;
import top.yongyan0624.entity.SysUserRole;
import top.yongyan0624.entity.Vote;
import top.yongyan0624.entity.VoteUser;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author yongyan
 * @since 2021-09-03
 */
@RestController
@RequestMapping("/vote")
public class VoteController extends BaseController {

    @GetMapping("/list")
    public Result list(String title, Long userId){
        Page<Vote> pageData = voteService.page(getPage(), new QueryWrapper<Vote>()
                .like(StrUtil.isNotBlank(title), "title", title).orderByDesc("create_time"));

        //处理查询出来的voteList数据
        handleVoteList(userId, pageData);

        return Result.success(pageData);
    }

    @GetMapping("/info/{id}")
    public Result info(@PathVariable("id") Long id, Long userId) {

        Vote vote = voteService.getById(id);
        Assert.notNull(vote, "找不到该投票信息");

        //获取全部选项
        List<String> optionList = StrUtil.split(vote.getOption(), ',', true, true);

        //获取投票情况
        List<VoteUser> voteUsers = voteUserService.list(new QueryWrapper<VoteUser>().eq("vote_id", id));
        if (voteUsers.size() > 0){
            HashMap<Integer,Integer> optionMap = new HashMap<>();
            //遍历每一行有关该投票的投票记录
            voteUsers.forEach(voteUser -> {
                //将该记录的投票内容转换为集合
                List<String> voteOption = StrUtil.split(voteUser.getOption(), ',', true, true);
                //遍历投票内容
                voteOption.forEach(v -> {
                    //用下标当key
                    int index = optionList.indexOf(v);
                    //每次查出一项投票内容，累计票数自增
                    optionMap.merge(index, 1, Integer::sum);
                });
            });
            vote.setOptionMap(optionMap);
        }

        //获取当前用户投票情况
        HashMap<String, Long> map = new HashMap<>();
        map.put("user_id",userId);
        map.put("vote_id",id);

        //处理单个投票Info
        handleVoteInfo(map, vote, optionList);

        return Result.success(vote);
    }

    @GetMapping("/listByUserId")
    public Result listByUserId(String title, Long userId){
        Page<Vote> pageData = voteService.page(getPage(), new QueryWrapper<Vote>().eq("user_id",userId)
                .like(StrUtil.isNotBlank(title), "title", title).orderByDesc("create_time"));

        //处理查询出来的voteList数据
        handleVoteList(userId, pageData);

        return Result.success(pageData);
    }

    @GetMapping("/listByCastVote")
    public Result listByCastVote(String title, Long userId){
        //根据userId查询他投过的所有票的id
        Set<Long> voteIds = voteUserService.list(new QueryWrapper<VoteUser>().eq("user_id", userId))
                .stream().map(voteUser -> voteUser.getVoteId()).collect(Collectors.toSet());
        //通过票下标获取所有票信息
        Page<Vote> pageData = voteService.page(getPage(), new QueryWrapper<Vote>().in("id",voteIds)
                .like(StrUtil.isNotBlank(title), "title", title).orderByDesc("create_time"));

        //处理查询出来的voteList数据
        handleVoteList(userId, pageData);

        return Result.success(pageData);
    }

    private void handleVoteList(Long userId, Page<Vote> pageData) {
        HashMap<String, Long> map = new HashMap<>();
        map.put("user_id", userId);

        pageData.getRecords().forEach(vote -> {
            //获取全部选项
            List<String> optionList = StrUtil.split(vote.getOption(), ',', true, true);

            map.put("vote_id", vote.getId());
            handleVoteInfo(map, vote, optionList);
        });
    }

    private void handleVoteInfo(HashMap<String, Long> map, Vote vote, List<String> optionList) {
        VoteUser voteUser = voteUserService.getOne(new QueryWrapper<VoteUser>().allEq(map));
        if (voteUser != null) {
            //获取当前用户选择的选项
            List<String> voteOption = StrUtil.split(voteUser.getOption(), ',', true, true);
            //将 当前用户选择的选项 转化成下标
            ArrayList<Integer> voteIndex = new ArrayList<>();
            voteOption.forEach(v -> voteIndex.add(optionList.indexOf(v)));
            vote.setVoteIndex(voteIndex);
        }

        //获取投过票的全部用户
        List<SysUser> userList = sysUserService.listByVoteId(vote.getId());

        vote.setOptionList(optionList);
        vote.setUser(sysUserService.getById(vote.getUserId()));
        vote.setVoteUserList(userList);
    }

    @PostMapping("/save")
    public Result save(@RequestBody Vote vote){
        String option = StrUtil.join(",", vote.getOptionList());
        vote.setOption(option);
        voteService.save(vote);
        return Result.success(vote);
    }

    @PostMapping("/update")
    @PreAuthorize("hasAuthority('vote:update')")
    public Result update(@RequestBody Vote vote){
        String option = StrUtil.join(",", vote.getOptionList());
        vote.setOption(option);
        voteService.updateById(vote);
        return Result.success(vote);
    }

    @Transactional
    @PostMapping("/delete")
    @PreAuthorize("hasAuthority('vote:delete')")
    public Result delete(@RequestBody Long[] ids) {

        voteService.removeByIds(Arrays.asList(ids));
        voteUserService.remove(new QueryWrapper<VoteUser>().in("vote_id", ids));

        return Result.success("");
    }

    @PostMapping("/castVote")
    public Result castVote(@RequestBody VoteUser voteUser){
        String option = StrUtil.join(",", voteUser.getOptionList());
        voteUser.setOption(option);

        HashMap<String, Long> map = new HashMap<>();
        map.put("vote_id",voteUser.getVoteId());
        map.put("user_id",voteUser.getUserId());

        voteUserService.saveOrUpdate(voteUser,new UpdateWrapper<VoteUser>().allEq(map));

        return Result.success(voteUser);
    }
}
